using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Colman.Rpg.Connection;
using Colman.Rpg.Messaging;

namespace Colman.Rpg.Npc
{
    /// <summary>
    /// The world as you know it - NPC game.
    /// </summary>
    public partial class WorldForm : ConnectionAwareForm
    {
        /// <summary>
        /// Creates a new instance of <see cref="WorldForm" />.
        /// </summary>
        public WorldForm()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Raises the <see cref="Form.Load" /> event.
        /// </summary>
        /// <param name="e">An <see cref="EventArgs" /> that contains the event data.</param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            ClientEndPoint.Instance.SendMessage(new CreateWorldRequest());

            this.UseWaitCursor = true;
        }

        /// <summary>
        /// Processes a command key.
        /// </summary>
        /// <param name="msg">A <see cref="Message"/>, passed by reference, that represents the Win32 message to process.</param>
        /// <param name="keyData">One of the <see cref="Keys"/> values that represents the key to process.</param>
        /// <returns>
        /// true if the keystroke was processed and consumed by the control;
        /// otherwise, false to allow further processing.
        /// </returns>
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            switch (keyData)
            {
                case Keys.W:
                    this.MovePlayer(0, -1);
                    break;
                case Keys.A:
                    this.MovePlayer(-1, 0);
                    break;
                case Keys.S:
                    this.MovePlayer(0, 1);
                    break;
                case Keys.D:
                    this.MovePlayer(1, 0);
                    break;
                default:
                    return base.ProcessCmdKey(ref msg, keyData);
            }

            return true;
        }

        private void MovePlayer(int xDiff, int yDiff)
        {
            Point newPosition = Point.Add(this.worldDisplay.DataSource.PlayerPosition, new Size(xDiff, yDiff));

            if (newPosition.X < 0)
                newPosition.Offset(this.worldDisplay.DataSource.Size, 0);
            else if (newPosition.X >= this.worldDisplay.DataSource.Size)
                newPosition.Offset(-this.worldDisplay.DataSource.Size, 0);

            if (newPosition.Y < 0)
                newPosition.Offset(0, this.worldDisplay.DataSource.Size);
            else if (newPosition.Y >= this.worldDisplay.DataSource.Size)
                newPosition.Offset(0, -this.worldDisplay.DataSource.Size);

            switch (this.worldDisplay.DataSource[newPosition.X, newPosition.Y])
            {
                case TileType.Grass:
                    this.worldDisplay.DataSource.PlayerPosition = newPosition;
                    break;
                case TileType.Monster:
                    ClientEndPoint.Instance.SendMessage(new FightMonsterRequest());
                    this.worldDisplay.DataSource.PlayerPosition = newPosition;
                    break;
            }
        }

        /// <summary>
        /// Called when a message is received from the server.
        /// </summary>
        /// <param name="sender">The object that raised the event.</param>
        /// <param name="e">The message arguments.</param>
        protected override void OnMessageReceived(object sender, MessageReceivedEventArgs e)
        {
            if (e.Message is CreateWorldResponse)
            {
                this.worldDisplay.DataSource = ((CreateWorldResponse)e.Message).CreatedWorld;
                this.worldDisplay.DataSource.PlayerPositionChanged += new EventHandler(DataSource_PlayerPositionChanged);

                this.UseWaitCursor = false;
            }
            else if (e.Message is FightMonsterResponse)
            {
                FightMonsterResponse response = (FightMonsterResponse)e.Message;

                Battles.BattleForm battle = new Colman.Rpg.Battles.BattleForm();
                battle.Player = response.Player;
                battle.Opponent = response.Monster;

                if (battle.ShowDialog(this) == DialogResult.Cancel)
                {
                    // You died. Go back to main.
                    this.Close();
                }
            }
            else if (e.Message is PlayerLevelledUpResponse)
            {
                PlayerLevelledUpResponse response = (PlayerLevelledUpResponse)e.Message;

                if (response.Player.Name == ClientEndPoint.Instance.UserName)
                {
                    CharacterSheetForm form = new CharacterSheetForm();
                    form.SetPlayer(response.Player, response.PointsOwedForLevellingUp);

                    form.ShowDialog(this);
                }
            }
        }

        private void DataSource_PlayerPositionChanged(object sender, EventArgs e)
        {
            this.worldDisplay.SnapToPlayer();
        }
    }
}